﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace XCrawler
{
    /// <summary>
    /// 【字符串】工作解析器
    /// </summary>
    public class StringWorkerParser : ICrawlerParser
    {
        /// <summary>
        /// 可解析的ContentType
        /// 默认: "text/html", "application/x-javascript", "application/javascript", "text/css", "text/js", "text/vue", "text/xml", "application/xhtml+xml", "text/plain"
        /// </summary>
        public string[] ContentTypes { get; set; } = new string[] { "text/html", "application/x-javascript", "application/javascript", "text/css", "text/js", "text/vue", "text/xml", "application/xhtml+xml", "text/plain" };

        /// <summary>
        /// 解析器处理函数
        /// </summary>
        /// <param name="crawler">爬虫</param>
        /// <param name="parserBag">爬虫返回信息包</param>
        /// <returns></returns>
        public virtual async Task DoWorkAsync(ICrawler crawler, ParserBag parserBag)
        {
            if (parserBag.StatusCode != HttpStatusCode.OK)
            {
                return;
            }

            if (!IsTextContent(parserBag.ContentType))
            {
                return;
            }

            if (parserBag.ContentCharset.ToLower().Contains("gb2312", "gbk"))
            {
                Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            }

            using (var ResponseStream = parserBag.ResponseBuffer)
            {
                //读取数据流转换成文本
                var content = string.Empty;
                if (parserBag.ContentEncoding.ToLower().Contains("gzip"))//解压
                {
                    using (GZipStream destream = new GZipStream(ResponseStream, CompressionMode.Decompress))
                    {
                        content = await destream.ReadToEndAsync(Encoding.GetEncoding(parserBag.ContentCharset)).ConfigureAwait(false);
                    }
                }
                else if (parserBag.ContentEncoding.ToLower().Contains("deflate"))//解压
                {
                    using (DeflateStream destream = new DeflateStream(ResponseStream, CompressionMode.Decompress))
                    {
                        content = await destream.ReadToEndAsync(Encoding.GetEncoding(parserBag.ContentCharset)).ConfigureAwait(false);
                    }
                }
                else
                {
                    content = await ResponseStream.ReadToEndAsync(Encoding.GetEncoding(parserBag.ContentCharset)).ConfigureAwait(false);
                }
                parserBag.SourceText = content.Trim();
            }
        }

        /// <summary>
        /// 是否为文本类型
        /// </summary>
        /// <param name="contentType"></param>
        /// <returns></returns>
        private bool IsTextContent(string contentType)
        {
            return this.ContentTypes.Where(x => contentType.StartsWith(x, StringComparison.OrdinalIgnoreCase)).Any();
        }
    }
}
